use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_void};
use std::ptr;

trait IQHelloTrait {}

// 定义与 C 头文件匹配的 IQHello 类型
#[repr(C)]
pub struct IQHello {
    _private: [u8; 0], // 不透明类型
}

// 匹配原始 C++ 的 std::string
#[repr(C)]
pub struct StdString {
    ptr: *mut c_char,
    len: usize,
    capacity: usize,
}

// 实现 C++ 虚函数表
#[repr(C)]
struct IQHelloVTable {
    getHello: extern "C" fn(*const IQHello) -> StdString,
}

// 全局虚函数表
static VTABLE: IQHelloVTable = IQHelloVTable { getHello: getHello };

// Rust 实现结构体
struct RustHelloImpl;

impl RustHelloImpl {
    fn getHello(&self) -> String {
        "Hello, World!(Rust Cpp Style)".to_string()
    }
}

// 导出函数实现
#[no_mangle]
pub extern "C" fn impl_t() -> i32 {
    return 2; // Cpp 类型插件
}

#[no_mangle]
pub extern "C" fn createIQHello() -> *mut IQHello {
    // 分配内存时包含虚函数表指针
    let layout = std::alloc::Layout::new::<*const IQHelloVTable>();
    unsafe {
        let ptr = std::alloc::alloc(layout) as *mut *const IQHelloVTable;
        if ptr.is_null() {
            return ptr::null_mut();
        }
        ptr.write(&VTABLE);
        ptr as *mut IQHello
    }
}

#[no_mangle]
pub extern "C" fn deleteIQHello(ptr: *mut IQHello) {
    if ptr.is_null() {
        return;
    }
    unsafe {
        let vtable_ptr = ptr as *mut *const IQHelloVTable;
        std::alloc::dealloc(
            vtable_ptr as *mut u8,
            std::alloc::Layout::new::<*const IQHelloVTable>(),
        );
    }
}

// 虚函数实现
#[no_mangle]
pub extern "C" fn getHello(this: *const IQHello) -> StdString {
    // 这里实际调用 Rust 实现
    let s = RustHelloImpl.getHello();
    let cstr = CString::new(s).unwrap();
    let len = cstr.as_bytes().len();
    StdString {
        ptr: cstr.into_raw(),
        len,
        capacity: len + 1,
    }
}

// 字符串释放函数
#[no_mangle]
pub extern "C" fn IQHello_freeString(s: *mut c_char) {
    if !s.is_null() {
        unsafe {
            let _ = CString::from_raw(s);
        }
    }
}
